package com.junxonline.plat.aspect;

import com.google.gson.Gson;
import com.junxonline.common.dao.vo.ResultVO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;

import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author JunX
 * @ClassName: HttpLogAspect
 * @Description: HTTP请求日志切面
 */

@Aspect
@Component
public class HttpLogAspect {

    private Logger logger = LogManager.getLogger();

    private ThreadLocal<Long> startTime = new ThreadLocal<Long>();

    /**
     * 定义切面
     * 拦截所有项目的所有Controller
     */
    @Pointcut("execution(* com..controller..*Controller.*(..))")
    public void log() {

    }

    /**
     * 请求日志输出
     *
     * @param joinPoint 切入点
     */
    @Before("log()")
    public void before(JoinPoint joinPoint) {

        // 开始计算请求耗时
        startTime.set(System.currentTimeMillis());

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        logger.info("************************ 收到请求 ************************");

        Gson gson = new Gson();
        logger.info("请求地址：" + request.getRequestURL());
        logger.info("请求类型：" + request.getMethod());
        logger.info("请求主机IP：" + getIpAddr(request));
        logger.info("请求方法路径：" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("请求参数：" + gson.toJson(joinPoint.getArgs()));

        logger.info("*********************************************************");
    }

    @AfterThrowing(pointcut = "log()", throwing = "e")
    public void doAfterThrowing(Exception e) {
        logger.info("************************ 抛出异常 ************************");

        logger.info("异常名称：" + e.getClass());
        logger.info("异常信息：" + e.getMessage());

        logger.info("*********************************************************");
    }

    /**
     * 返回数据日志输出
     */
    @AfterReturning(pointcut = "log()", returning = "result")
    public void doAfterReturning(ResultVO result) {
        logger.info("************************ 返回数据 ************************");

        Gson gson = new Gson();
        logger.info("返回响应码：" + result.getErrorCode().toString());
        logger.info("返回响应信息：" + result.getErrorMsg().toString());
        logger.info("返回数据：" + gson.toJson(result.getReturnData()));
        logger.info("请求耗时：" + (System.currentTimeMillis() - startTime.get()) + "ms");

        logger.info("*********************************************************");
    }

    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

}
